﻿#ifndef Event_h__2013_7_31__12_13
#define Event_h__2013_7_31__12_13

#include "df_macro.h"

#ifndef WIN32
#	include <semaphore.h>
#endif // !WIN32
#include <condition_variable> 

namespace df
{

	class Event
	{
	public:
#if defined(WIN32) && !defined(DF_EVENT_C11)
		//初始不置位,手工重置
		inline Event()
		{
			hEvent = CreateEvent(
				NULL,			// 默认安全属性
				false,			// 重置方式
				false,			// 初始状态
				NULL			// 未命名
				);
			if (hEvent == NULL)
			{
				DF_ERR(tcc_("CreateEvent failed!"));
			}
		}

		Event(Event && e)
		{
			hEvent = e.hEvent;
			e.hEvent = 0;
		}

		inline ~Event(void)
		{
			if (hEvent)
				CloseHandle(hEvent);
		}


		//*******************************************
		// Summary : 等待事件置位
		// Parameter - DWORD time : 等待超时值(毫秒)
		// Returns - bool : 成功与否(未超时)
		//*******************************************
		bool Wait(DWORD time = INFINITE, df::ErrWrap err = nullptr)
		{
			//等待窗口初始化完成
			auto res = WaitForSingleObject(hEvent, time);
			if (res == WAIT_FAILED)
			{
				DF_LASTERR(err, tcc_("WaitForSingleObject failed!"));
				return false;
			}
			return (res == WAIT_OBJECT_0);
		}


		inline void Set()
		{
			if (SetEvent(hEvent))
				return;
			DF_ERR(tcc_("SetEvent failed !"));
			return;
		}

		inline void SetAll()
		{
			if (SetEvent(hEvent))
				return;
			DF_ERR(tcc_("SetEvent failed !"));
			return;
		}


	private:
		HANDLE hEvent;
#elif defined(__APPLE__) ||  defined(DF_EVENT_C11)
	public:
		inline Event()
		{

		}
		//*******************************************
		// Summary : 等待信号量置位
		// Parameter - DWORD time : 等待超时值(毫秒)
		// Returns - bool : 成功与否(未超时)
		//*******************************************
		bool Wait(uint32_t ti = 0, df::ErrWrap err = nullptr)
		{
			std::unique_lock<std::mutex> lck(mtx_);
			if (ti)
				return cv_.wait_for(lck, std::chrono::milliseconds(ti)) != std::cv_status::timeout;

			cv_.wait(lck); // 当前线程被阻塞, 当全局标志位变为 true 之后,

			return true;
		}

		inline void Set()
		{
			std::unique_lock <std::mutex> lck(mtx_);

			cv_.notify_one();
		}
		inline void SetAll()
		{
			std::unique_lock <std::mutex> lck(mtx_);

			cv_.notify_all();
		}

	private:
		std::mutex mtx_; // 全局互斥锁.
		std::condition_variable cv_; // 全局条件变量.
#else
	public:
		inline Event()
		{
			//FALSE初始是否置位
			if (sem_init(&sem_, 0, FALSE) != 0)
			{
				DF_ERR(tcc_("sem_init failed!"));
			}
		}



		~Event(void)
		{
			//if (sem_)
			sem_destroy(&sem_);
		}

		//*******************************************
		// Summary : 等待信号量置位
		// Parameter - DWORD time : 等待超时值(毫秒)
		// Returns - bool : 成功与否(未超时)
		//*******************************************
		bool Wait(DWORD ti = 0, df::ErrWrap err = nullptr)
		{
#ifdef __APPLE__
#else
			if(ti)
			{
				//struct timeval tt;
				//gettimeofday(&tt,NULL);

				struct timespec ts;
				//只精确到秒
				ts.tv_sec=::time(NULL) + ti / 1000;
				ts.tv_nsec=0;
				int res = sem_timedwait(&sem_, &ts);
				if(res == 0)
					return true;

				if(df::GetError() == ETIMEDOUT)
					return false;

				DF_LASTERR(err, tcc_("sem_timedwait failed!"));
			}
#endif

			if(sem_wait(&sem_) != 0)
				DF_LASTERR(err,tcc_("sem_wait failed !"));

			return true;
		}


		inline bool Set()
		{
			if (sem_post(&sem_) == 0)
				return;
			DF_ERR(tcc_("sem_post failed !"));
			return;
		}

		inline bool SetAll()
		{
			if (sem_post(&sem_) == 0)
				return;
			DF_ERR(tcc_("sem_post failed !"));
			return;
		}
	private:
		sem_t sem_;
#endif


		DF_DISABLE_COPY_ASSIGN(Event);
	};

}
#endif // Event_h__2013_7_31__12_13
